package org.ix.dynamicapis.configure;

import org.ix.dynamicapis.configure.models.*;
import org.ix.dynamicapis.configure.utils.*;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class ApiTemplates extends BaseApiTemplate {

    /**
     * 接口全路径和配置的映射
     */
    private Map<String, ConfigModel> dsConfigMap = new HashMap<>();

    /**
     * DataSource和接口全路径集合的映射
     */
    private Map<String, Set<String>> dsPathMap = new HashMap<>();

    /**
     * 接口全路径和配置的映射
     */
    private Map<String, ConfigModel> pathConfigMap = new HashMap<>();

    public ApiTemplates(String getApisUrl, String system, RedisTemplate<String, Object> redisTemplate) {
        super(getApisUrl, system, redisTemplate);
    }

    public ApiTemplates(String getApisUrl, String system, RedisTemplate<String, Object> redisTemplate, List<ConfigModel> configs) throws Exception {
        this(getApisUrl, system, redisTemplate);
        if (configs == null || configs.isEmpty()) return;
        for (ConfigModel config : configs) {
            this.addConfig(config);
        }
    }

    public ApiTemplates addConfig(ConfigModel config) throws Exception {
        dsPathMap.put(config.getDataSource(), new HashSet<>());
        dsConfigMap.put(config.getDataSource(), config);
        log.info("正在刷新配置，数据源" + config.getDataSource());
        refresh(config.getDataSource(), null, null, null);
        return this;
    }

    public ApiTemplates addConfig(String dataSource, JdbcTemplate jdbcTemplate, Configuration configuration) throws Exception {
        return addConfig(new ConfigModel(dataSource, jdbcTemplate, configuration));
    }

    @Override
    void setCache(String dataSource, List<ApiModel> apis) throws ParserConfigurationException, SAXException, IOException {

        ConfigModel config = dsConfigMap.get(dataSource);

        long timestamp = new Date().getTime();
        if (apis != null && !apis.isEmpty()) {
            for (ApiModel api : apis) {
                String fullPath = ApiTemplateUtils.getFullPath(api.getVersion(), api.getTopic(), api.getApiPath());

                // 添加路径和配置的映射
                pathConfigMap.put(fullPath, config);

                ApiSqlModel apiSqlModel = ApiTemplateUtils.getApiSqlModel(config, api, timestamp);
                super.mybatisSqlMap.put(fullPath, apiSqlModel);
            }

            // 添加数据源和全路径集合的映射
            Set<String> set = apis.stream()
                    .map(item -> ApiTemplateUtils.getFullPath(item.getVersion(), item.getTopic(), item.getApiPath()))
                    .collect(Collectors.toSet());
            Set<String> paths = dsPathMap.get(dataSource);
            paths.addAll(set);
        }
    }

    @Override
    void delCache(String dataSource, String fullPath) {

        // 当前数据源对应的所有全路径
        Set<String> paths = dsPathMap.get(dataSource);

        if (StringUtils.isBlank(fullPath)) {
            // 删除当前数据源对应的所有路径和配置的映射
            for (String path : paths) {
                super.mybatisSqlMap.remove(path);
                pathConfigMap.remove(path);
            }
            // 清空数据源对应的全路径集合
            paths.clear();
        } else {
            super.mybatisSqlMap.remove(fullPath);
            // 从路径和配置的映射中删除
            pathConfigMap.remove(fullPath);
            // 删除数据源对应的全路径集合中的指定路径
            paths.remove(fullPath);
        }
    }

    @Override
    ConfigModel getConfigByPath(String fullPath) {
        return pathConfigMap.getOrDefault(fullPath, null);
    }
}
